package com.xiaoxi.common.util;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xiaoxi.common.constant.enumeration.statuscode.system.FileSystemEnums;
import com.xiaoxi.common.exception.BMSException;
import com.xiaoxi.service.circulation.ExportDataToExcelService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.data.domain.PageRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author xiaoxi
 * @version 1.0
 * @date 2022/7/31 14:34
 */
@Slf4j
public class ExcelUtils {

    /**
     * 用户信息导出类
     *
     * @param response 响应
     * @param fileName 文件名
     */
    public static <T> void exportExcel(HttpServletRequest request, HttpServletResponse response
            , String fileName, ExportDataToExcelService exportDataToExcelService, T objDTO) throws BMSException {
        //声明输出流
        OutputStream os = null;
        //设置响应头
        setResponseHeader(request, response, fileName);

        IPage<T> iPage = null;

        try {
            //获取输出流
            os = response.getOutputStream();

            SXSSFWorkbook wb = new SXSSFWorkbook();

            Sheet sheet1 = wb.createSheet("sheet1");

            int excelRow = 0;
            // 1. 处理表头
            dealTableHeader(exportDataToExcelService.tableHeader(), excelRow++, sheet1);

            // 2. 分页处理表中数据
            // 在这里进行分页计算
            iPage = exportDataToExcelService.tableContent(objDTO, PageRequest.of(1, 2000));
            long total = iPage.getTotal();

            for (int page = 2; total > 0; total -= 1, ++page) {

                excelRow = dealTableContent(iPage.getRecords(), excelRow, sheet1);
                iPage = exportDataToExcelService.tableContent(objDTO, PageRequest.of(page, 2000));

            }


            // 解决文件名导出乱码
            byte[] bfileName = StringUtils.isEmpty(fileName) ? "默认文件名.xls".getBytes() : fileName.getBytes();
            os.write(bfileName.length);
            os.write(bfileName);
            wb.write(os);


        } catch (IOException e) {
            log.error("发生异常：{}", e.getMessage());
            throw new BMSException(FileSystemEnums.FILE_STREAM_ERROR);
        } finally {
            try {
                // 关闭输出流
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                log.error("关闭流出现异常：{}", e.getMessage());
            }
        }
    }

    /**
     * 设置浏览器响应头
     *
     * @param response
     * @param fileName
     */
    private static void setResponseHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
        try {

            final String userAgent = request.getHeader("USER-AGENT");
            String finalFileName = null;
            if (StringUtils.isNotBlank(userAgent) && userAgent.contains("Firefox")) {
                // firefox
                finalFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            } else {
                // others
                finalFileName = URLEncoder.encode(fileName, "UTF-8");
            }

            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + finalFileName);
            response.setHeader("Access-Control-Allow-Origin", "*");

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 处理表头数据
     *
     * @param columnList
     * @param excelRow
     * @param sheet1
     */
    private static void dealTableHeader(List<String> columnList, Integer excelRow, Sheet sheet1) {

        //创建标题行
        Row titleRow = sheet1.createRow(excelRow);
        for (int i = 0; i < columnList.size(); i++) {
            //创建该行下的每一列，并写入标题数据
            Cell cell = titleRow.createCell(i);
            cell.setCellValue(columnList.get(i));
        }

    }

    /**
     * 写入表中数据
     *
     * @param dataList
     * @param excelRow
     * @param sheet1
     */
    private static <T> Integer dealTableContent(List<T> dataList, Integer excelRow, Sheet sheet1) {
        if (dataList != null && dataList.size() > 0) {
            //外层for循环创建行
            for (T data : dataList) {
                Row dataRow = sheet1.createRow(excelRow++);
                //内层for循环创建每行对应的列，并赋值
                String[] content = data.toString().split("☆");
                for (int j = 0; j < content.length; j++) {
                    Cell cell = dataRow.createCell(j);
                    cell.setCellValue(content[j]);
                }
            }
        }
        return excelRow;
    }
}
